package com.yz.demo.config;

import com.yz.demo.util.XmlUtil;
import okhttp3.FormBody;
import okhttp3.RequestBody;
import okhttp3.ResponseBody;
import retrofit2.Converter;
import retrofit2.Retrofit;

import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.Map;

/**
 * @author shanchong
 * @date 2019-07-11
 **/
public class MyConverterFactory extends Converter.Factory {

    public static MyConverterFactory create(){
        return new MyConverterFactory();
    }

    @Override
    public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
        return new MyResponseConverter(type);
    }

    @Override
    public Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
        return new MyRequestConverter(type);
    }

    static final class MyResponseConverter implements Converter<ResponseBody, Object> {

        Class clazz;

        MyResponseConverter(Type type){
            this.clazz = (Class) type;
        }

        @Override
        public Object convert(ResponseBody value) {
            try {
                final String string = value.string();
                final String xml = URLDecoder.decode(string, "GBK");
                final Object o = clazz.newInstance();
                final Map<String, String> xml2Map = XmlUtil.xml2Map(xml);
                final Method[] methods = clazz.getMethods();
                for (final Method method : methods) {
                    final String name = method.getName();
                    if (name.startsWith("set")) {
                        final String setname = name.replace("set", "");
                        method.invoke(o, xml2Map.get(setname.substring(0, 1).toLowerCase() + setname.substring(1)));
                    }
                }
                return o;
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        }
    }

    static final class MyRequestConverter implements Converter<Object,RequestBody> {

        private Class clazz;

        MyRequestConverter(Type clazz){
            this.clazz = (Class) clazz;
        }

        @Override
        public RequestBody convert(Object value) throws IOException {
            final FormBody.Builder builder = new FormBody.Builder();
            final String string = clazz.cast(value).toString();
            builder.add("param", URLEncoder.encode(string,"GBK"));
            return builder.build();
        }
    }
}
